package com.idp.common.token.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.jwt.JWTUtil;
import com.idp.common.constants.RedisKeyConstant;
import com.idp.common.enums.UserTypeEnum;
import com.idp.common.model.LoginInfo;
import com.idp.common.redis.RedisCache;
import com.idp.common.utils.ContextUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Map;

@Component
public class TokenService {

	private static final String AUTHORIZATION = "Authorization";
	private static final String AUTH_PREFIX = "";
	private static final String JWT_SECRET = "abc123456";
	private static final long TOKEN_EXPIRE_TIME_WEB = 60 * 2;
	private static final long TOKEN_EXPIRE_TIME_APP = 60 * 24 * 7;

	@Autowired
	private RedisCache redisCache;

	public void saveToken(LoginInfo loginInfo) {

		Map<String, Object> payload = BeanUtil.beanToMap(loginInfo);
		String token = JWTUtil.createToken(payload, JWT_SECRET.getBytes());
		loginInfo.setToken(token);

		this.refreshToken(loginInfo);
	}

	public LoginInfo getLoginInfo() {

		HttpServletRequest request = ContextUtil.getRequest();

		String authorization = request.getHeader(AUTHORIZATION);

		if(StrUtil.isNotEmpty(authorization)) {

			String token = authorization.replace(AUTH_PREFIX, "");

			if(StrUtil.isNotEmpty(token)) {

				LoginInfo loginInfo = redisCache.getObject(RedisKeyConstant.TOKEN_FOLDER + token);

				if(loginInfo != null) {
					return loginInfo;
				}
			}
		}

		return null;
	}

	public void verifyToken(LoginInfo loginInfo) {

		if(!UserTypeEnum.MOBILE.code.equals(loginInfo.getUserType())) {

			long diff = DateUtil.between(new Date(), new Date(loginInfo.getExpireTime()), DateUnit.MINUTE);

			if(diff <= TOKEN_EXPIRE_TIME_WEB/2) {

				this.refreshToken(loginInfo);
			}
		}
	}

	private void refreshToken(LoginInfo loginInfo) {

		long tokenExpireTime = TOKEN_EXPIRE_TIME_WEB;

		if(UserTypeEnum.MOBILE.code.equals(loginInfo.getUserType())) {
			tokenExpireTime = TOKEN_EXPIRE_TIME_APP;
		}

		Date expireTime = DateUtil.offsetMinute(new Date(), (int)tokenExpireTime);
		loginInfo.setExpireTime(expireTime.getTime());
		redisCache.saveObject(RedisKeyConstant.TOKEN_FOLDER + loginInfo.getToken(), loginInfo, tokenExpireTime);
	}

	public LoginInfo removeToken() {

		LoginInfo loginInfo = getLoginInfo();

		if(loginInfo != null) {

			redisCache.deleteObject(RedisKeyConstant.TOKEN_FOLDER + loginInfo.getToken());

			return loginInfo;
		}

		return null;
	}

}
